/*
 Contém a função main, módulo inicial que chama os outros módulos
 */

#define NOME_JVM "jvm"

#include "common.h"
#include "list.h"
#include "stack.h"
#include "classfile.h"
#include "run.h"
#include "frame.h"

static void print_uso();

stack *framestack;
class_list *methodarea;
class_file *mainclass;

int main(int argc, char **argv) {
	int method_index;
	method_info *method;
	method_frame *main_frame;
	int class_index;	/*  índice do arquivo class no argv */

	/*Verifica se foram especificados corretamente os argumentos de entrada */
	if (argc < 2) {
		print_uso();
	}

	else if (strcmp("-c", argv[1]) == 0) {
		PRINT = 1;
		class_index = 2;
	}

	else if (strcmp("-v", argv[1]) == 0) {
		VERBOSE = 1;
		class_index = 2;
	}

	else {
		class_index = 1;
	}

	/*Alocar lista*/
	METHODAREA = (class_list *) new_list();

	/*Alocar stack*/
	FRAMESTACK = (stack *) new_stack();
	if (VERBOSE) printf("Iniciando leitura do .class:\n");
	loadClass(argv[class_index]);
	if (VERBOSE) printf("Leitura Concluida:\n");
	MAINCLASS = METHODAREA->first->class;

	/*Imprimir estrtutura do .class*/
	if (PRINT) printclass(MAINCLASS);

	/*inicia execução*/
	init_instructions();

	/*Buscar method clinit*/
	method_index = get_method_index("<clinit>");

	/* checa se existe indicie valido*/
	if (method_index > 0) {
		method = (method_info *) get_method("<clinit>");

		/* cria frame para <clinit> */
		main_frame = (method_frame *) new_frame(method,
				MAINCLASS->constant_pool, method_index);

		/*coloca frame na pilha*/
		push_stack(FRAMESTACK, main_frame);

		/*executa frame <clinit>*/
		execute(FRAMESTACK->top->frame, MAINCLASS);
	}

	/*Buscar method main*/
	method_index = get_method_index("main");
	method = (method_info *) get_method("main");

	/* cria frame para main */
	main_frame = (method_frame *) new_frame(method, MAINCLASS->constant_pool,
			method_index);

	/*coloca frame na pilha*/
	push_stack(FRAMESTACK, main_frame);

	/*executa frame main*/
	execute(FRAMESTACK->top->frame, MAINCLASS);

	return 0;
}


/* Imprime a forma que o programa deve ser chamado e encerra. */
void print_uso() {
	printf("JAVA VIRTUAL MACHINE\n"
		"uso: %s [opção] [class]\n"
		"Opções:\n"
		"\t-c\tClass, apenas imprime a estrutura do arquivo class\n"
		"\t-v\tVerbose, imprime as ações à medida que as executa\n", NOME_JVM);
	exit(0);
}
